package cn.jjxx.modules.activiti.controller;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

import net.sf.json.JSONArray;

import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.CustomProperty;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.UserTask;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.framework.customutil.ListSortUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import cn.jjxx.core.common.entity.ZtreeEntity;
import cn.jjxx.core.model.AjaxJson;
import cn.jjxx.core.model.PageJson;
import cn.jjxx.core.query.data.PropertyPreFilterable;
import cn.jjxx.core.query.data.Queryable;
import cn.jjxx.core.query.wrapper.EntityWrapper;
import cn.jjxx.core.utils.ObjectUtils;
import cn.jjxx.core.utils.SpringContextHolder;
import cn.jjxx.core.utils.StringUtils;
import cn.jjxx.core.utils.TreeBuilder;
import cn.jjxx.modules.activiti.config.Contacts;
import cn.jjxx.modules.activiti.entity.ActivitiModelEntity;
import cn.jjxx.modules.activiti.entity.ActivitiProcessDefinitionEntity;
import cn.jjxx.modules.activiti.entity.MyUserTask;
import cn.jjxx.modules.activiti.extend.ExtBpmnJsonConverter;
import cn.jjxx.modules.activiti.extend.ExtBpmnXMLConverter;
import cn.jjxx.modules.activiti.extend.ExtProperty;
import cn.jjxx.modules.activiti.extend.ExtUserTaskJsonConverter;
import cn.jjxx.modules.activiti.service.impl.FlowService;

import cn.jjxx.modules.sys.entity.User;
import cn.jjxx.modules.sys.service.IUserService;
import cn.jjxx.modules.sys.utils.UserUtils;
import cn.jjxx.modules.workflow.controller.ActReTypeController;
import cn.jjxx.modules.workflow.controller.ActSignTemplateController;
import cn.jjxx.modules.workflow.entity.ActReType;
import cn.jjxx.modules.workflow.entity.ActSignTemplate;
import cn.jjxx.modules.workflow.service.IActReTypeService;
import cn.jjxx.modules.workflow.service.IActSignTemplateService;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;


@Controller  
@Scope("prototype")   
@RequestMapping("${admin.url.prefix}/activiti/deploy")
public class ActivitiModelController extends FlowService{
	
	@Autowired
	private IUserService userService;
	@Autowired
    protected IActReTypeService actReTypeService;
	@Autowired
    protected IActSignTemplateService signTemplateService;
	
	/**
	 * @Description: 跳转至导入流程模型界面 .<br>
	 * @author 郑成功 .<br>
	 * @date 2018-5-30 下午11:21:08.<br>
	 */
	@RequestMapping(value="/impModel",method=RequestMethod.GET) 
	public String  impModel(HttpServletRequest request, HttpServletResponse response){
		ActivitiModelEntity entity = new ActivitiModelEntity();
		String nodeId = request.getParameter("nodeId");
        ActReType type = actReTypeService.selectById(nodeId);
        if(!ObjectUtils.isNullOrEmpty(type)){
        	entity.setModelType(nodeId);
        	request.setAttribute("parentname", type.getName());
        }
		request.setAttribute("data",entity);
 		return display("impModel");
	}
	
	/**
	 * @Description: 跳转至人员设置界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @return String 跳转.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-12-14 下午9:39:00 .<br>
	 */
	@RequestMapping(value="/predef/asigneeSetting",method=RequestMethod.GET) 
	public String  asigneeSetting(HttpServletRequest request, HttpServletResponse response){
		MyUserTask myTask = new MyUserTask();
		String modelId = request.getParameter("modelId");
		String taskDefId = request.getParameter("taskDefId");
		List<User> uList = userService.selectList(null);
		List<UserTask> utasks = flowService.findUserTasks(modelId);
		List<Group> groups = identityService.createGroupQuery().list();
		for(UserTask ut:utasks){
			if(ut.getId().equals(taskDefId)){
				myTask.setName(ut.getName());
				myTask.setDocumentation(ut.getDocumentation());
				CustomProperty sortNumProperty = getCustomProperty(ut, ExtProperty.SORT_NUM);
				if(sortNumProperty!=null){
					myTask.setSortNum(sortNumProperty.getSimpleValue());
				}
				CustomProperty customProperty = getCustomProperty(ut, ExtProperty.SEND_MSG_TEMPLET);
				if(customProperty!=null){
					myTask.setSendMsgTemplet(customProperty.getSimpleValue());
				}
				if(ut.getAssignee()!=null){
					User user = userService.selectById(ut.getAssignee());
					if(user!=null){
						myTask.setAssignee(user.getId());
						myTask.setUserName(user.getRealname());
					}
					myTask.setDealingType(MyUserTask.ASSIGNEE);
				}else if(ut.getCandidateGroups().size()>0){
					String candidateGroupName = StringUtils.join(getCandidateGroupName(ut.getCandidateGroups(), groups),",");
					myTask.setCandidateGroup(StringUtils.join(ut.getCandidateGroups(),","));
					myTask.setDealingType(MyUserTask.CANDIDATE_GROUP);
					myTask.setCandidateGroupName(candidateGroupName);
				}else if(ut.getCandidateUsers().size()>0){
					String candidateUserName = StringUtils.join(getCandidateUserName(ut.getCandidateUsers(), uList),",");
					myTask.setCandidateUser(StringUtils.join(ut.getCandidateUsers(),","));
					myTask.setDealingType(MyUserTask.CANDIDATE_USERS);
					myTask.setCandidateUserName(candidateUserName);
				}
			}
		}
		request.setAttribute("data",myTask );
 		return display("predef/asigneeSetting");
	}
	
	/**
	 * @Description: 跳转至用户任务节点配置界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @return String 跳转.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-12-14 下午9:39:00 .<br>
	 */
	@RequestMapping(value="/predef/userTaskList",method=RequestMethod.GET) 
	public String  userTaskList(HttpServletRequest request, HttpServletResponse response){
 		return display("predef/userTaskList");
	}
	
	/**
	 * @Description: 跳转到用户分组界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @author 郑成功 .<br>
	 * @date 2017-12-14 下午7:54:33 .<br>
	 */
	@RequestMapping(value="/group/list",method=RequestMethod.GET)  
    public String  groupList(HttpServletRequest request, HttpServletResponse response){  
    	return display("group/groupList");
    }
	
	/**
	 * @Description: 跳转到用户组配置用户界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @author 郑成功 .<br>
	 * @date 2017-12-14 下午7:54:33 .<br>
	 */
	@RequestMapping(value="/group/userList",method=RequestMethod.GET)  
    public String  userList(HttpServletRequest request, HttpServletResponse response){  
    	return display("group/userList");
    }
	
	/**
	 * @Description: 跳转到流程设计list界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @return String .<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-17 上午11:03:41.<br>
	 */
	@RequestMapping(value="/modeler/list",method=RequestMethod.GET)  
    public String  modelerList(HttpServletRequest request, HttpServletResponse response){  
		List<ZtreeEntity> zlist = SpringContextHolder.getBean(ActReTypeController.class).getActTypeTreeList();
		List<ZtreeEntity> list = TreeBuilder.bulid(zlist);
    	String content = JSON.toJSONString(list);
    	request.setAttribute("ztreeList", content);
    	return display("modelList");
    }
	@RequestMapping(value="/flowAudit",method=RequestMethod.GET)  
    public String  flowAudit(HttpServletRequest request, HttpServletResponse response){  
    	return display("flowAudit");
    }
	
	/**
	 * @Description:  .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>   
	 * @return void .<br> 
	 * @throws .<br>
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 上午8:39:10.<br>
	 */
	@RequestMapping(value="/model/ajaxList",method = { RequestMethod.GET, RequestMethod.POST })  
	public void ModelList(Queryable queryable,PropertyPreFilterable propertyPreFilterable,
			HttpServletRequest request, HttpServletResponse response){
		List<ActivitiModelEntity> medelList = new ArrayList<ActivitiModelEntity>();
		String nodeId = request.getParameter("nodeId");
		int page = queryable.getPageable().getPageNumber()-1;
		int pageSize = queryable.getPageable().getPageSize();
		ModelQuery query = repositoryService.createModelQuery();
		if(StringUtils.isNotEmpty(nodeId)){
			query.modelCategory(nodeId);
		}
		List<Model> list = query.list();
		List<ProcessDefinition> preDefList = repositoryService.createProcessDefinitionQuery().list();
		List<ActReType> reList = actReTypeService.selectList(null);
		SerializeFilter filter = propertyPreFilterable.constructFilter(ActivitiModelEntity.class);
		for(Model m:list){
			ActivitiModelEntity model = new ActivitiModelEntity();
			model.setId(m.getId());
			model.setName(m.getName());
			model.setKey(m.getKey());
			model.setCategory(m.getCategory());
			for(ActReType re:reList){
				if(StringUtils.isNotEmpty(m.getCategory())&&m.getCategory().equals(re.getId())){
					model.setModelType(re.getName());
				}
			}
			model.setCreateTime(m.getCreateTime());
			model.setDiscription(String.valueOf(JSONObject.parseObject(m.getMetaInfo()).get("description")));
			boolean isDeploy = checkIsDeploy(preDefList, m.getKey());
			if(isDeploy){
				model.setStatus(1);
			}else {
				model.setStatus(0);
			}
			medelList.add(model);
		}
		String content = JSON.toJSONString(medelList,filter);
		StringUtils.printJson(response, content);
	}
	
	/**
	 * @Description: 检测当前模型是否已部署 .<br>
	 * @param preDefList 流程定义集合 .<br>
	 * @param key 模型的key.<br>
	 * @return boolean 是否部署.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 下午4:39:28.<br>
	 */
	private static boolean checkIsDeploy(List<ProcessDefinition> preDefList,String key){
		for(ProcessDefinition pd:preDefList){
			if(pd.getKey().equals(key)){
				return true;
			}
		}
		return false;
	}
	
	/**
	 * @Description: 跳转至流程版本监控界面 .<br>
	 * @param request http请求.<br>
	 * @param response http响应.<br>
	 * @return String 返回流程版本监控界面.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 下午5:51:11.<br>
	 */
	@RequestMapping(value="/predef/list",method=RequestMethod.GET)  
    public String  predefList(HttpServletRequest request, HttpServletResponse response){  
    	return display("predef/predefList");
    }
	
	/**
	 * @Description: 获取流程版本监控数据 .<br>
	 * @param queryable grid的绑定属性 .<br>
	 * @param request http请求 .<br>
	 * @param response http响应 .<br>  
	 * @param modelId 模型Id .<br>    
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 下午5:53:38.<br>
	 */
	@RequestMapping(value="/predef/ajaxList",method = { RequestMethod.GET, RequestMethod.POST })  
	public void predefList(Queryable queryable,HttpServletRequest request, HttpServletResponse response,String modelId){
		List<ActivitiProcessDefinitionEntity> pdList = new ArrayList<ActivitiProcessDefinitionEntity>();
		int page = queryable.getPageable().getPageNumber()-1;
		int pageSize = queryable.getPageable().getPageSize();
		Model model = repositoryService.createModelQuery().modelId(modelId).singleResult();
		List<ProcessDefinition> predefList = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey(model.getKey()).orderByProcessDefinitionVersion()
				.asc().listPage(page,pageSize);
		Long total = repositoryService.createProcessDefinitionQuery().processDefinitionKey(model.getKey()).count();
		for(ProcessDefinition pd:predefList){
			ActivitiProcessDefinitionEntity predef = new ActivitiProcessDefinitionEntity();
			predef.setId(pd.getId());
			predef.setName(pd.getName());
			if(pd.getName()==null){
				predef.setName(model.getName());
			}
			predef.setKey(pd.getKey());
			predef.setVersion(pd.getVersion());
			predef.setDeploymentId(pd.getDeploymentId());
			predef.setResourceName(pd.getResourceName());
			predef.setDiagramResourceName(pd.getDiagramResourceName());
			predef.setDescription(pd.getDescription());
			predef.setSuspensionState(1);
			pdList.add(predef);
		}
		PageJson<ActivitiProcessDefinitionEntity> pagejson = new PageJson<>(page,pageSize,total,pdList);
		String content = JSON.toJSONString(pagejson);
		StringUtils.printJson(response, content);
	}
	
	
	/**
	 * @Description: 跳转至流程模型设计界面 .<br>
	 * @param request http请求 .<br>
	 * @param response http响应 .<br>
	 * @return String 返回界面.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-17 上午11:05:34.<br>
	 */
    @RequestMapping(value="/modeler",method=RequestMethod.GET)  
    public String  modeler(HttpServletRequest request, HttpServletResponse response){  
    	return display("modeler");
    }
    
	/**
	 * @Description: 创建模型,保存相关信息 .<br>
	 * @param request http请求 .<br>
	 * @param response http响应 .<br>
	 * @return String .<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-17 上午11:02:14.<br>
	 */
	@RequestMapping(value = "createModel", method = RequestMethod.GET)
	public String _showCreateModel(HttpServletRequest request, HttpServletResponse response) {	
		ActivitiModelEntity entity = new ActivitiModelEntity();
		String nodeId = request.getParameter("nodeId");
        ActReType type = actReTypeService.selectById(nodeId);
        if(!ObjectUtils.isNullOrEmpty(type)){
        	entity.setModelType(nodeId);
        	request.setAttribute("parentname", type.getName());
        }
		request.setAttribute("data", entity);
		return display("modelEdit");
	}
	
	/**
	 * @Description: 跳转至修改流程模型基础界面 .<br>
	 * @param id 模型Id .<br>
	 * @author 郑成功 .<br>
	 * @date 2018-12-6 下午5:02:35.<br>
	 */
	@RequestMapping(value = "updateModel", method = RequestMethod.GET)
	public String showUpdateModel(HttpServletRequest request, HttpServletResponse response,String id) {	
		ActivitiModelEntity entity = new ActivitiModelEntity();
		Model model = repositoryService.getModel(id);
		ActReType type = actReTypeService.selectById(model.getCategory());
		entity.setId(model.getId());
		entity.setModelName(model.getName());
		entity.setModelType(type.getId());
		entity.setTypeName(type.getName());
		JSONObject json = StringUtils.isNotEmpty(model.getMetaInfo())?JSONObject.parseObject(model.getMetaInfo()):new JSONObject();
		entity.setDiscription(json.getString("description"));
		request.setAttribute("data", entity);
		return display("modelEdit");
	}
	
	/**
	 * @Description: 修改模型基本信息 .<br>
	 * @param request http请求.<br>
	 * @param m 模型实体.<br>
	 * @author 郑成功 .<br>
	 * @date 2018-12-6 下午5:06:43.<br>
	 */
	@RequestMapping(value = "updateModel", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson updateModel(HttpServletRequest request,ActivitiModelEntity m) {	
		AjaxJson j = new AjaxJson();
		try {
			Model model = repositoryService.getModel(m.getId());
			ObjectMapper objectMapper = new ObjectMapper();
			ObjectNode modelObjectNode = objectMapper.createObjectNode();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, m.getModelName());
            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
            String description = m.getDiscription();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            model.setMetaInfo(modelObjectNode.toString());
			model.setCategory(m.getModelType());
			model.setName(m.getModelName()); 
			//设置模型XML里面的名称，并保存xml文件
			byte[] modelEditorSource = repositoryService.getModelEditorSource(m.getId());
			JsonNode editorNode = new ObjectMapper().readTree(modelEditorSource);
			JsonNode properties =  editorNode.findValue("properties");
			if(properties!=null){
				ObjectNode newProperties = (ObjectNode) properties;
				newProperties.put("name", m.getModelName());
				String newByte = editorNode.toString();
		        repositoryService.addModelEditorSource(m.getId(),newByte.getBytes("utf-8") );
			}
			repositoryService.saveModel(model);
		} catch (Exception e) {
			j.setMsg("修改模型失败");
		}
		return j;
	}
    
    /**
     * @Description: 创建模型,保存模型的基本信息 .<br>
     * @param request http请求.<br>
     * @param response http响应.<br>
     * @param model 模型的实体.<br>
     * @return AjaxJson .<br> 
     * @author 郑成功 .<br>
     * @date 2017-11-15 下午5:39:24.<br>
     */
	@RequestMapping(value = "createModel", method = RequestMethod.POST)
	@ResponseBody
    public AjaxJson createModel(HttpServletRequest request, HttpServletResponse response,ActivitiModelEntity model) {
    	AjaxJson j = new AjaxJson();
        try {
        	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        	 
        	RepositoryService repositoryService = processEngine.getRepositoryService();
        	 
            ObjectMapper objectMapper = new ObjectMapper();
            ObjectNode editorNode = objectMapper.createObjectNode();
            editorNode.put(Contacts.modelKey.id.toString(), Contacts.modelValue.canvas.toString());
            editorNode.put(Contacts.modelKey.resourceId.toString(), Contacts.modelValue.canvas.toString());
            ObjectNode stencilSetNode = objectMapper.createObjectNode();
            stencilSetNode.put(Contacts.modelKey.namespace.toString(), Contacts.ACTIVITI_NAMESPACE);
            editorNode.put(Contacts.modelKey.stencilset.toString(), stencilSetNode);
            Model modelData = repositoryService.newModel();

            ObjectNode modelObjectNode = objectMapper.createObjectNode();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, model.getModelName());
            modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1);
            String description = model.getDiscription();
            modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
            modelData.setMetaInfo(modelObjectNode.toString());
            modelData.setName(model.getModelName());
            modelData.setKey(model.getModelKey());
            modelData.setCategory(model.getModelType());
            //保存模型
            repositoryService.saveModel(modelData);
            repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8")); 
            j.setData(modelData.getId());
            j.setMsg("保存成功");
            return j;
        } catch (Exception e) {
        	j.setMsg("保存失败!<br />原因:" + e.getMessage());
        	j.setRet(AjaxJson.RET_FAIL);
            return j;
        }
    }
	
	/**
	 * @Description: 根据模型Id,部署流程 .<br>
	 * @param request http请求.<br>
	 * @param modelId 模型Id.<br>
	 * @return AjaxJson 返回ajax处理结果.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 下午2:35:56.<br>
	 */
	@SuppressWarnings("static-access")
	@RequestMapping(value = "deployModel", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson deploy(HttpServletRequest request,String modelId) {
		AjaxJson j = new AjaxJson();
		try {
			Model modelData = repositoryService.getModel(modelId);
			ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
			byte[] bpmnBytes = null;
			
			//UserTask自定义扩展属性
			ExtBpmnJsonConverter bjcp = new ExtBpmnJsonConverter();
			ExtUserTaskJsonConverter.fillTypes(bjcp.getConvertersToBpmnMap(), bjcp.getConvertersToJsonMap());

			BpmnModel model = new ExtBpmnJsonConverter().convertToBpmnModel(modelNode);
			bpmnBytes = new ExtBpmnXMLConverter().convertToXML(model);
			String mName = modelData.getName();
			String processName = mName + Contacts.ACTIVITI_BPMN_SUFF;
			repositoryService.createDeployment().name(mName).addString(processName, new String(bpmnBytes, "utf-8")).deploy();
			//获取上一个版本的模板，保存到当前版本
			String modelKey = modelData.getKey();
			saveSignTemplate(modelKey, request);
			j.setMsg("流程部署成功");
			return j;
		} catch (Exception e) {
			e.printStackTrace();
			j.setRet(AjaxJson.RET_FAIL);
			j.setMsg("流程部署失败!<br />原因:"+e.getMessage());
		}
		return j;
	}
	
	/**
	 * @Description: 保存签字模板 .<br>
	 * @param deployId 部署Id.<br>
	 * @param request 问题.<br>   
	 * @author 郑成功 .<br>
	 * @date 2018-8-27 下午3:18:21.<br>
	 */
	private void saveSignTemplate(String deployId,HttpServletRequest request){
		List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery()
				.processDefinitionKey(deployId)
				.orderByProcessDefinitionVersion()
				.desc()
				.list();
		if(list.size()>1){
			ActSignTemplate actSignTemplate = new ActSignTemplate();
			EntityWrapper<ActSignTemplate> wrapper = new EntityWrapper<ActSignTemplate>(ActSignTemplate.class);
			wrapper.eq("preDefId", list.get(1).getId());
			ActSignTemplate template = signTemplateService.selectOne(wrapper);
			if(!ObjectUtils.isNullOrEmpty(template)){
				ProcessDefinition proDefInfo = list.get(0);
				actSignTemplate.setPreDefId(proDefInfo.getId());
				actSignTemplate.setSignTemplate(template.getSignTemplate());
				actSignTemplate.setSmsTemplate(template.getSmsTemplate());
				SpringContextHolder.getBean(ActSignTemplateController.class).doSave(actSignTemplate, request, null);
			}
		}
	}
	
	/**
	 * @Description: 根据模型Id,删除未发布的模型 .<br>
	 * @param request http请求.<br>
	 * @param modelId 模型Id.<br>
	 * @return AjaxJson 返回处理结果.<br> 
	 * @author 郑成功 .<br>
	 * @date 2017-11-16 下午2:44:43.<br>
	 */
	@RequestMapping(value = "delModel", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson delModel(HttpServletRequest request,String modelId) {
		AjaxJson j = new AjaxJson();
		try {
			repositoryService.deleteModel(modelId);
			j.setMsg("删除模型成功!");
		} catch (Exception e) {
			j.setRet(AjaxJson.RET_FAIL);
			j.setMsg("删除模型失败!<br />原因:"+e.getMessage());
		}
		return j;
	}
	
	/**
	 * @Description: 导入流程模型 .<br>
	 * @param request  .<br>
	 * @param response  .<br>
	 * @return AjaxJson .<br> 
	 * @author 郑成功 .<br>
	 * @date 2018-3-20 下午2:07:27.<br>
	 */
	@RequestMapping(value = "/import/model")
	@ResponseBody
	public AjaxJson importModel(HttpServletRequest request,HttpServletResponse response,ActivitiModelEntity actModel){
		AjaxJson j = new AjaxJson();
		j.setMsg("模型导入成功!");
    	response.setContentType("text/plain");
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
				request.getSession().getServletContext());
		if (multipartResolver.isMultipart(request)&&StringUtils.isNotEmpty(actModel.getModelType())) { // 判断request是否有文件上传
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator<String> ite = multiRequest.getFileNames();
			while (ite.hasNext()) {
				try {
					//获取文件
					MultipartFile file = multiRequest.getFile(ite.next());
					CommonsMultipartFile cFile = (CommonsMultipartFile) file;
			        DiskFileItem fileItem = (DiskFileItem) cFile.getFileItem();
			        InputStream inputStream = fileItem.getInputStream();
			        if(!StringUtils.isNotEmpty(actModel.getModelName())){
			        	actModel.setModelName(fileItem.getName());
			        }
			        if(!StringUtils.isNotEmpty(actModel.getDiscription())){
			        	actModel.setDiscription(fileItem.getName());
			        }
			        // 转换所需的内容
					XMLInputFactory xmlFactory  = XMLInputFactory.newInstance(); 
					BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
					BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
			        //获取流文建
			        XMLStreamReader reader = xmlFactory.createXMLStreamReader(inputStream);
			        BpmnModel bpmnModel = xmlConverter.convertToBpmnModel(reader);
					bpmnModel.getProcesses().get(0).setId(actModel.getModelKey());  // 只以第一个流程定义做关联
					JsonNode jsonNode = jsonConverter.convertToJson(bpmnModel);
			        //创建模板
			        AjaxJson json = createModel(request, response, actModel);
			        String modelId = String.valueOf(json.getData());
			        repositoryService.addModelEditorSource(modelId, jsonNode.toString().getBytes("utf-8"));
			        //保存模板数据
				}catch(Exception e){
					j.setMsg("模型导入!<br />原因:" + e.getMessage());
					j.setRet(AjaxJson.RET_FAIL);
				}
			}
		}else{
			j.setMsg("导入失败，流程类型或文件未上传");
		}
		return j;
	}
	
	/**
	 * @Description: 下载流程模型 .<br>
	 * @param response .<br>
	 * @param modelId .<br>   
	 * @return void .<br> 
	 * @author 郑成功 .<br>
	 * @date 2018-3-20 下午2:06:40.<br>
	 */
	@RequestMapping(value = "/export/model")
	public void exportModel(HttpServletResponse response,String modelId){
		response.setCharacterEncoding("UTF-8");  
	    response.setContentType("application/json; charset=utf-8");
	    response.setContentType("application/force-download");//应用程序强制下载
	    try {
	        Model modelData = repositoryService.getModel(modelId);
	        BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
	        //获取节点信息
	        byte[] arg0 = repositoryService.getModelEditorSource(modelData.getId());
	        JsonNode editorNode = new ObjectMapper().readTree(arg0);
	        //将节点信息转换为xml
	        BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
	        BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
	        byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);
	 
	        ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
	        String filename = modelData.getName() + ".bpmn20.xml";
	        response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(filename, "UTF-8"));
	        IOUtils.copy(in, response.getOutputStream());
			response.flushBuffer();
	    } catch (Exception e){
	        PrintWriter out = null;
	        try {
	            out = response.getWriter();
	        } catch (IOException e1) {
	            e1.printStackTrace();
	        }
	        out.write("未找到对应数据");
	        e.printStackTrace();
	    }
	}
	
	/**
	 * @description 获取指定流程的用户任务节点信息.<br>
	 * @param processDefinitionId 流程定义Id.<br>
	 * @param processDefinitionId 任务类型.<br>
	 * @throws IOException 
	 * @throws JsonProcessingException 
	 */
	@RequestMapping(value="findActUserTasks",method = { RequestMethod.GET, RequestMethod.POST })  
	@ResponseBody
	public List<MyUserTask> findActUserTasks(String modelId,String taskType) throws Exception{
		List<MyUserTask> list = new ArrayList<MyUserTask>();
		byte[] byts = repositoryService.getModelEditorSource(modelId);
		//UserTask自定义扩展属性
		ExtBpmnJsonConverter bjcp = new ExtBpmnJsonConverter();
		ExtUserTaskJsonConverter.fillTypes(bjcp.getConvertersToBpmnMap(), bjcp.getConvertersToJsonMap());
		BpmnModel model = new BpmnModel();
		JsonNode  editorNode = new ObjectMapper().readTree(byts);			
		model = bjcp.convertToBpmnModel(editorNode);
		List<User> uList = userService.selectList(null);
		List<Group> groups = identityService.createGroupQuery().list();
		if(model != null){
			Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();			
			for(FlowElement e:flowElements){
				if(e instanceof UserTask){
					UserTask userTask = (UserTask) e;
					MyUserTask mut = new MyUserTask();
					User u = UserUtils.getUser(userTask.getAssignee(), uList);
					mut.setId(userTask.getId());
					mut.setName(userTask.getName());
					mut.setDocumentation(userTask.getDocumentation());
					mut.setDueDate(userTask.getDueDate());
					CustomProperty sortnumProperty = getCustomProperty(userTask, ExtProperty.SORT_NUM);
					if(sortnumProperty!=null){
						mut.setSortNum(sortnumProperty.getSimpleValue());
					}
					CustomProperty customProperty = getCustomProperty(userTask, ExtProperty.SEND_MSG_TEMPLET);
					if(customProperty!=null){
						mut.setSendMsgTemplet(customProperty.getSimpleValue());
					}
					if(userTask.getExecutionListeners().size()>0){
						mut.setHasExecutionLenser(true);
					}
					if(userTask.getTaskListeners().size()>0){
						mut.setHasTaskLenser(true);
					}
					if(StringUtils.isNotEmpty(userTask.getAssignee())){
						mut.setDealingType(MyUserTask.ASSIGNEE);
						mut.setUserName(u.getRealname());
					}else if(userTask.getCandidateGroups().size()>0){
						String candidateGroupName = StringUtils.join(getCandidateGroupName(userTask.getCandidateGroups(), groups),",");
						mut.setCandidateGroup(StringUtils.join(userTask.getCandidateGroups(),","));
						mut.setDealingType(MyUserTask.CANDIDATE_GROUP);
						mut.setCandidateGroupName(candidateGroupName);
					}else if(userTask.getCandidateUsers().size()>0){
						String candidateUserName = StringUtils.join(getCandidateUserName(userTask.getCandidateUsers(), uList),",");
						mut.setCandidateUser(StringUtils.join(userTask.getCandidateUsers(),","));
						mut.setDealingType(MyUserTask.CANDIDATE_USERS);
						mut.setCandidateUserName(candidateUserName);
					}
					list.add(mut);
				}
			}
		}
		ListSortUtil<MyUserTask> sorts = new ListSortUtil<MyUserTask>();
		sorts.sort(list, "sortNum", "asc");
		return list;
	}
	
	/**
	 * @Description: 获取候选人 名称集合.<br>
	 * @param userIds 候选人Id集合.<br>
	 * @param users 候选人实体集合.<br>
	 * @author 郑成功 .<br>
	 * @date 2018-7-25 上午10:39:48.<br>
	 */
	private List<String> getCandidateUserName(List<String> userIds,List<User> users){
		List<String> userNames = new ArrayList<String>();
		for(String id:userIds){
			for(User u:users){
				if(id.equals(u.getId())){
					userNames.add(u.getRealname());
				}
			}
		}
		return userNames;
	}
	
	/**
	 * @Description: 获取组的名称集合 .<br>
	 * @param groupIds 组Id.<br>
	 * @param groups 组实体.<br>
	 * @author 郑成功 .<br>
	 * @date 2018-7-20 下午4:32:06.<br>
	 */
	private List<String> getCandidateGroupName(List<String> groupIds,List<Group> groups){
		List<String> groupNames = new ArrayList<String>();
		for(String id:groupIds){
			for(Group g:groups){
				if(id.equals(g.getId())){
					groupNames.add(g.getName());
				}
			}
		}
		return groupNames;
	}
	
	/**
	 * @Description: 修改设置流程节点处理人 .<br>
	 * @param modelId 模型Id.<br>
	 * @param muTask 我的任务实体.<br>
	 * @return AjaxJson .<br> 
	 * @author 郑成功 .<br>
	 * @date 2018-2-24 上午9:06:54.<br>
	 */
	@RequestMapping(value = "setFlowUser", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson setFlowUser(HttpServletRequest request,String modelId,MyUserTask muTask) throws Exception{
		AjaxJson j = new AjaxJson();
		byte[] byts = repositoryService.getModelEditorSource(modelId);
		JsonNode  editorNode = new ObjectMapper().readTree(byts);
		BpmnJsonConverter jc = new BpmnJsonConverter();
		BpmnModel model = jc.convertToBpmnModel(editorNode);
	
		model = jc.convertToBpmnModel(editorNode);
		UserTask myuTask = null;
		if(model != null){
			Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();			
			for(FlowElement e:flowElements){
				if(e instanceof UserTask){
					UserTask userTask = (UserTask) e;
					if(userTask.getId().equals(muTask.getId())){
						if(StringUtils.isNotEmpty(muTask.getSendMsgTemplet())){
							//获取自定义属性短信发送模板
							CustomProperty customProperty = getCustomProperty(userTask, ExtProperty.SEND_MSG_TEMPLET);
							if(customProperty!=null){
								customProperty.setSimpleValue(muTask.getSendMsgTemplet());
							}else{
								customProperty = new CustomProperty();
								customProperty.setName(ExtProperty.SEND_MSG_TEMPLET);
								customProperty.setSimpleValue(muTask.getSendMsgTemplet());
								userTask.getCustomProperties().add(customProperty);
							}
						}
						if(StringUtils.isNotEmpty(muTask.getSortNum())){
							//获取自定义属性短信发送模板
							CustomProperty customProperty = getCustomProperty(userTask, ExtProperty.SORT_NUM);
							if(customProperty!=null){
								customProperty.setSimpleValue(muTask.getSortNum());
							}else{
								customProperty = new CustomProperty();
								customProperty.setName(ExtProperty.SORT_NUM);
								customProperty.setSimpleValue(muTask.getSortNum());
								userTask.getCustomProperties().add(customProperty);
							}
						}
						myuTask = userTask;
						if(muTask.getDealingType()==MyUserTask.ASSIGNEE){
							myuTask.setAssignee(muTask.getAssignee());
							myuTask.setCandidateUsers(new ArrayList<String>());
							myuTask.setCandidateGroups(new ArrayList<String>());
						}else if(muTask.getDealingType()==MyUserTask.CANDIDATE_GROUP){
							List<String> candidateGroups = Arrays.asList(muTask.getCandidateGroup().split(","));
							myuTask.setCandidateGroups(candidateGroups);
							myuTask.setCandidateUsers(new ArrayList<String>());
							myuTask.setAssignee(null);
						}else if(muTask.getDealingType()==MyUserTask.CANDIDATE_USERS){
							List<String> candidateUsers = Arrays.asList(muTask.getCandidateUser().split(","));
							myuTask.setCandidateUsers(candidateUsers);
							myuTask.setAssignee(null);
							myuTask.setCandidateGroups(new ArrayList<String>());
						}
						break;
					}
				}
			}
			JsonNode nodes = jc.convertToJson(model);
			repositoryService.addModelEditorSource(modelId, String.valueOf(nodes).getBytes("utf-8"));
		}
		return j;
	}
	
	/**
	 * @Description: 跳转至用户组界面 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value="/usergroup/groupList",method=RequestMethod.GET) 
	public String userGroupList(HttpServletRequest request, HttpServletResponse response){
		request.setAttribute("data",new ActivitiModelEntity());
 		return display("usergroup/groupList");
	}
	
	/**
	 * @Description: 跳转至导入用户界面 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-20 上午9:32:47.<br>
	 */
	@RequestMapping(value="selectUserList",method=RequestMethod.GET) 
	public String selectUserList(HttpServletRequest request, HttpServletResponse response,String groupId){
		if(StringUtils.isNotEmpty(groupId)){
			request.setAttribute("data",new ActivitiModelEntity());
			List<org.activiti.engine.identity.User> users = identityService.createUserQuery().memberOfGroup(groupId).list();
			List<String> userIds = new ArrayList<String>();
			for(org.activiti.engine.identity.User u:users){
				userIds.add(u.getId());
			}
			request.setAttribute("userIds", JSONArray.fromObject(userIds));		
		}
 		return display("usergroup/selectUserList");
	}
	
	/**
	 * @Description: 选择分组 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-20 上午11:47:20.<br>
	 */
	@RequestMapping(value="selectGroupList",method=RequestMethod.GET) 
	public String selectGroupList(HttpServletRequest request, HttpServletResponse response){
		return display("usergroup/selectGroupList");
	}
	
	
	/**
	 * @Description: 跳转至新增或者修改用户组界面 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value="/usergroup/edit",method=RequestMethod.GET) 
	public String groupEdit(HttpServletRequest request, HttpServletResponse response,String id){
		GroupEntity group = new GroupEntity();
		if(StringUtils.isNotEmpty(id)){
			group = (GroupEntity) identityService.createGroupQuery().groupId(id).singleResult();
		}
		request.setAttribute("data", group);
 		return display("usergroup/edit");
	}
 
	/**
	 * @Description: 跳转至用户组与人员设置界面 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "userGroupSet", method = RequestMethod.GET)
	public String userGroupSet(HttpServletRequest request, HttpServletResponse response){
		request.setAttribute("data",new ActivitiModelEntity());
 		return display("usergroup/userGroupSet");
	}

	/**
	 * @Description: ajax请求，获取用户组列表查询 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "ajaxGroupList", method = { RequestMethod.GET, RequestMethod.POST })
	public void ajaxGroupList(Queryable queryable,PropertyPreFilterable propertyPreFilterable,
			HttpServletRequest request, HttpServletResponse response){
		List<Group> list = identityService.createGroupQuery().list();
		List<GroupEntity> gList = new ArrayList<GroupEntity>();
		for(Group g:list){
			GroupEntity group = new GroupEntity();
			group.setId(g.getId());
			group.setName(g.getName());
			group.setType(g.getType());
			gList.add(group);
		}
		String content = JSON.toJSONString(gList);
		StringUtils.printJson(response, content);
	}
	
	/**
	 * @Description: ajax请求，获取用户列表查询 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "ajaxUserList", method = { RequestMethod.GET, RequestMethod.POST })
	public void ajaxUserList(Queryable queryable,PropertyPreFilterable propertyPreFilterable,
			HttpServletRequest request, HttpServletResponse response,String groupId){
		List<org.activiti.engine.identity.User> list = identityService.createUserQuery().memberOfGroup(groupId).list();
		List<UserEntity> uList = new ArrayList<UserEntity>();
		for(org.activiti.engine.identity.User u:list){
			UserEntity user = new UserEntity();
			user.setId(u.getId());
			user.setFirstName(u.getFirstName());
			user.setLastName(u.getLastName());
			user.setEmail(u.getEmail());
			uList.add(user);
		}
		String content = JSON.toJSONString(uList);
		StringUtils.printJson(response, content);
	}
	
	/**
	 * @Description: 保存用户组 .<br>
	 * @param request
	 * @param response
	 * @param group 组的实体 .<br>
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "saveGroup", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson saveGroup(HttpServletRequest request, HttpServletResponse response,GroupEntity group){
		AjaxJson j = new AjaxJson();
		j.setMsg("保存成功");
		try {
			if(!StringUtils.isNotEmpty(group.getId())){
				String id = StringUtils.randomUUID();
				group.setId(id);
			}
			identityService.saveGroup(group);
		} catch (Exception e) {
			e.printStackTrace();
			j.setRet(AjaxJson.RET_FAIL);
			j.setMsg("保存失败,原因："+e.getMessage());
		}
 		return j;
	}

	/**
	 * @Description: 保存用户组与人员的设置 .<br>
	 * @param request
	 * @param response
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:49:22.<br>
	 */
	@RequestMapping(value = "saveUserGroup", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson saveUserGroup(HttpServletRequest request, HttpServletResponse response,String groupId,String[] ids){
		AjaxJson j = new AjaxJson();
		j.setMsg("导入成功");
		List<String> userIds = Arrays.asList(ids);
		boolean flag = flowService.saveUserGroup(groupId, userIds);
		if(!flag){
			j.setMsg("导入失败");
			j.setRet(AjaxJson.RET_FAIL);
		}
 		return j;
	}


	/**
	 * @Description: 批量删除分组设置 .<br>
	 * @param request
	 * @param response
	 * @param ids 组的ID集合 .<br>
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "deleteGroup", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson deleteGroup(HttpServletRequest request, HttpServletResponse response,String[] ids){
		AjaxJson j = new AjaxJson();
		j.setMsg("删除分组成功");
		try {
			identityService.deleteGroup(ids[0]);
		} catch (Exception e) {
			e.printStackTrace();
			j.setRet(AjaxJson.RET_FAIL);
			j.setMsg("删除分组失败，原因:"+e.getMessage());
		}
 		return j;
	}
	
	/**
	 * @Description: 批量删除组用户 .<br>
	 * @param request
	 * @param groupId 组Id .<br>
	 * @param ids 组的ID集合 .<br>
	 * @author 郑成功 .<br>
	 * @date 2018-7-19 下午4:43:05.<br>
	 */
	@RequestMapping(value = "deleteGroupUser", method = RequestMethod.POST)
	@ResponseBody
	public AjaxJson deleteGroupUser(HttpServletRequest request, HttpServletResponse response,String groupId,String[] ids){
		AjaxJson j = new AjaxJson();
		List<String> userIds = Arrays.asList(ids);
		j.setMsg("删除组用户成功");
		boolean flag = flowService.deleteGroupUser(groupId, userIds);
		if(!flag){
			j.setRet(AjaxJson.RET_FAIL);
			j.setMsg("删除组用户失败，可能未有用户，请联系系统管理员");
		}
 		return j;
	}
}  
